package net.starwifi.duobao.service.impl;

import com.google.common.collect.Maps;
import net.starwifi.duobao.entity.Member;
import net.starwifi.duobao.entity.Payment;
import net.starwifi.duobao.entity.TradeRecord;
import net.starwifi.duobao.mvc.Page;
import net.starwifi.duobao.mvc.PageView;
import net.starwifi.duobao.repository.TradeRecordRepository;
import net.starwifi.duobao.service.*;
import net.starwifi.duobao.utils.CompressUtils;
import net.starwifi.duobao.utils.StringUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Administrator on 2015/9/29.
 */
@Service
public class TradeRecordServiceImpl extends BaseServiceImpl<TradeRecord,Long> implements TradeRecordService {
    /**
     * 导出文件的最大大小 超过这个大小会压缩
     */
    private final int MAX_EXPORT_FILE_SIZE = 10 * 1024 * 1024; //10MB
    private final String storePath = "upload/excel";
    private final String EXPORT_FILENAME_PREFIX = "excel";

    @Autowired
    MemberService memberService;
    @Autowired
    TradeRecordRepository tradeRecordRepository;


    @Autowired
    PaymentService paymentService;

    /** 退款*/
    @Transactional
    public void refunds(Long memberId,BigDecimal fee,String remarks,String outSn){
        String sn= StringUtils.getUUID();
        TradeRecord tradeRecord=new TradeRecord(sn,1,fee,remarks,memberId);
        tradeRecord.setTradeCat(4);
        tradeRecord.setOutSn(outSn);

        Member member=memberService.find(memberId);
        if(member.getVirtualCurrency()==null){
            member.setVirtualCurrency(fee);
        }else{
            member.setVirtualCurrency(member.getVirtualCurrency().add(fee));
        }
        tradeRecord.setBalance(member.getVirtualCurrency()); //变动之后
        tradeRecord.setMobile(member.getMobile());
        save(tradeRecord);
        memberService.update(member, "username", "salt", "password", "logo", "email", "isEnabled", "isLocked", "loginFailureCount", "lockedDate", "registerIp", "loginIp", "loginDate","mobile");
    }


    /** 后台充值
     * @param memberId
     *
     * */
    @Transactional
    public void adminRecharge(Long memberId,BigDecimal fee,String remarks,String outSn){
        String sn= StringUtils.getUUID();
        TradeRecord tradeRecord=new TradeRecord(sn,1,fee,remarks,memberId);
        tradeRecord.setTradeCat(0);
        tradeRecord.setOutSn(outSn);
        Member member=memberService.find(memberId);
        if(member.getVirtualCurrency()==null){
            member.setVirtualCurrency(fee);
        }else{
            member.setVirtualCurrency(member.getVirtualCurrency().add(fee));
        }
        tradeRecord.setBalance(member.getVirtualCurrency()); //变动之后
        tradeRecord.setMobile(member.getMobile());
        save(tradeRecord);
        memberService.update(member,"username","salt","password","logo","email","isEnabled","isLocked","loginFailureCount","lockedDate","registerIp","loginIp","loginDate","mobile");
    }

    /** 购物*/
    @Transactional
    public boolean buy(Long memberId,BigDecimal fee,String remarks,String outSn){
        String sn= StringUtils.getUUID();
        TradeRecord tradeRecord=new TradeRecord(sn,0,fee,remarks,memberId);
        tradeRecord.setTradeCat(2);
        tradeRecord.setOutSn(outSn);
        Member member=memberService.find(memberId);
        if(member.getVirtualCurrency()==null){
            member.setVirtualCurrency(BigDecimal.ZERO);
        }
        if(member.getVirtualCurrency().compareTo(fee)==-1){
            return false; //账户余额不足
        }
        BigDecimal lastAmount=member.getVirtualCurrency().subtract(fee); //新的账户余额
        tradeRecord.setBalance(member.getVirtualCurrency()); //变动之后
        member.setVirtualCurrency(lastAmount);
        tradeRecord.setMobile(member.getMobile());
        save(tradeRecord);
        memberService.update(member, "username", "salt", "password", "logo", "email", "isEnabled", "isLocked", "loginFailureCount", "lockedDate", "registerIp", "loginIp", "loginDate","mobile");
        return true;
    }


    /** 充值*/
    @Transactional
    public void     recharge(Long memberId,BigDecimal fee,String remarks,String outSn){
        String sn= StringUtils.getUUID();
        TradeRecord tradeRecord=new TradeRecord(sn,1,fee,remarks,memberId);
        tradeRecord.setTradeCat(0);
        tradeRecord.setOutSn(outSn);
        Member member=memberService.find(memberId);
        if(member.getVirtualCurrency()==null){
            member.setVirtualCurrency(fee);
        }else{
            member.setVirtualCurrency(member.getVirtualCurrency().add(fee));
        }
      Payment payment= paymentService.findBySn(outSn);

        tradeRecord.setMobile(member.getMobile());
        tradeRecord.setBalance(member.getVirtualCurrency()); //变动之后
        save(tradeRecord);
        memberService.update(member,"username","salt","password","logo","email","isEnabled","isLocked","loginFailureCount","lockedDate","registerIp","loginIp","loginDate","mobile");
    }

    /** 红包 */
    @Transactional
    public void hb(Long memberId,BigDecimal fee,String remarks,String outSn){
        String sn= StringUtils.getUUID();
        TradeRecord tradeRecord=new TradeRecord(sn,1,fee,remarks,memberId);
        tradeRecord.setTradeCat(1);
        tradeRecord.setOutSn(outSn);
        Member member=memberService.find(memberId);
        if(member.getVirtualCurrency()==null){
            member.setVirtualCurrency(fee);
        }else{
            member.setVirtualCurrency(member.getVirtualCurrency().add(fee));
        }
        tradeRecord.setBalance(member.getVirtualCurrency()); //变动之后
        tradeRecord.setMobile(member.getMobile());
        save(tradeRecord);
        memberService.update(member,"username","salt","password","logo","email","isEnabled","isLocked","loginFailureCount","lockedDate","registerIp","loginIp","loginDate","mobile");
    }

    @Transactional
    public  TradeRecord  findByoutSn(Long memberId,String outSn) {
        return tradeRecordRepository.findByoutSn( memberId,outSn);
    }

    @Override
    public String exportExcel2003WithUsermodel(String basePath, String contextRootPath, PageView pageView) {

        int perSheetRows = 60000; //每个sheet 6w条
        int totalRows = 0;
//        Long maxId = 0L;
        String resultURL="";
        String fileName = generateFilename(basePath, contextRootPath, "xls");
        File file = new File(fileName);
        BufferedOutputStream out = null;
        try {
            long beginTime = System.currentTimeMillis();

            HSSFWorkbook wb = new HSSFWorkbook();
            Sheet sheet = wb.createSheet();
            Row headerRow = sheet.createRow(0);

            Cell cell = headerRow.createCell(0);
            cell.setCellValue("编号");
            cell = headerRow.createCell(1);
            cell.setCellValue("变动金额");
            cell = headerRow.createCell(2);
            cell.setCellValue("操作后余额");
            cell = headerRow.createCell(3);
            cell.setCellValue("备注");
            cell = headerRow.createCell(4);
            cell.setCellValue("用户ID");
            cell = headerRow.createCell(5);
            cell.setCellValue("用户号码");
            cell = headerRow.createCell(6);
            cell.setCellValue("业务分类");
            cell = headerRow.createCell(7);
            cell.setCellValue("关联订单");
            cell = headerRow.createCell(8);
            cell.setCellValue("创建时间");


            totalRows = 1;
            double sumFee=0;

            pageView.setNumPerPage(200); //每次查询200行
            Long total=getMQueryCount(pageView.getFilters()); //记录总数
            int totalPage=(int) Math.ceil((double) total / (double) 200); //总页数
            int num=0;//序号
            try {
                for(int i=1;i<=totalPage;i++){
                    pageView.setPageNumber(i); //当前页
                    Page<TradeRecord> page = getScrollData(pageView);
                    DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                    for (TradeRecord data : page.getContent()) {
                        Row row = sheet.createRow(totalRows);

                        Cell datacell = row.createCell(0);
                        datacell.setCellValue(data.getSn());
                        datacell = row.createCell(1);
                        datacell.setCellValue(data.getFee().toString());
                        datacell = row.createCell(2);
                        datacell.setCellValue(data.getBalance().toString());
                        datacell = row.createCell(3);
                        datacell.setCellValue(data.getRemarks());
                        datacell = row.createCell(4);
                        datacell.setCellValue(data.getMemberId());
                        datacell = row.createCell(5);
                        datacell.setCellValue(data.getMobile());
                        String tradeCat="";
                        if(data.getTradeCat()==0){
                            tradeCat="充值";
                        }else if(data.getTradeCat()==1) {
                            tradeCat="转账";
                       }else if(data.getTradeCat()==2) {
                            tradeCat="购物";
                        }else if(data.getTradeCat()==3) {
                            tradeCat="理财";
                        }else{
                            tradeCat="退款";
                        }
                        datacell = row.createCell(6);
                        datacell.setCellValue(tradeCat);
                        datacell = row.createCell(6);
                        datacell.setCellValue(data.getOutSn());
                        datacell = row.createCell(8);
                        datacell.setCellValue(format.format(data.getCreateDate()));

                        totalRows++;
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            clear();
            out = new BufferedOutputStream(new FileOutputStream(file));
            wb.write(out);
            IOUtils.closeQuietly(out);
            if(needCompress(file)) {
                fileName = compressAndDeleteOriginal(fileName);
            }
            long endTime = System.currentTimeMillis();

            Map<String, Object> context = Maps.newHashMap();
            context.put("seconds", (endTime - beginTime) / 1000);
            context.put("url", fileName.replace(contextRootPath, ""));
            resultURL=fileName.replace(contextRootPath, "");
        } catch (Exception e) {
            IOUtils.closeQuietly(out);
            Map<String, Object> context = Maps.newHashMap();
            context.put("error", e.getMessage());
        }
        return resultURL;
    }

    private String compressAndDeleteOriginal(final String filename) {
        String newFileName = FilenameUtils.removeExtension(filename) + ".zip";
        compressAndDeleteOriginal(newFileName, filename);
        return newFileName;
    }

    private void compressAndDeleteOriginal(final String newFileName, final String... needCompressFilenames) {
        CompressUtils.zip(newFileName, needCompressFilenames);
        for(String needCompressFilename : needCompressFilenames) {
            FileUtils.deleteQuietly(new File(needCompressFilename));
        }
    }

    /**
     * 生成要导出的文件名
     * @param basePath
     * @param contextRootPath
     * @param extension
     * @return
     */
    private String generateFilename(final String basePath, final String contextRootPath, final String extension) {
        return generateFilename(basePath, contextRootPath, null, extension);
    }
    private String generateFilename(final String basePath, final String contextRootPath, Integer index, final String extension) {
        String path = FilenameUtils.concat(contextRootPath, storePath);
        path = FilenameUtils.concat(path, basePath);
        path = FilenameUtils.concat(
                path,
                EXPORT_FILENAME_PREFIX + "_" +
                        DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS") +
                        (index != null ? ("_" + index) : "") +
                        "." + extension);

        File file = new File(path);
        if(!file.exists()) {
            File parentFile = file.getParentFile();
            if(!parentFile.exists()) {
                parentFile.mkdirs();
            }
            return path;
        }
        return generateFilename(basePath, contextRootPath, extension);
    }
    private boolean needCompress(final File file) {
        return file.length() > MAX_EXPORT_FILE_SIZE;
    }


}
